﻿using SHZY.Common.Core.Manager;
using SHZY.Common.Core.Security;
using SHZY.ClayObject;
using SHZY.Common.Configuration;
using SHZY.Common.Models.NPOI;
using SHZY.DataEncryption;
using SHZY.Common.Enum;
using SHZY.Common.Extension;
using SHZY.Common.Filter;
using SHZY.Common.Security;
using SHZY.DependencyInjection;
using SHZY.DynamicApiController;
using SHZY.FriendlyException;
using SHZY.Business.Entitys.Dto.QmsBusiWorkorder;
using SHZY.Business.Entitys.Dto.QmsBusiWorkorderdetail;
using SHZY.Business.Entitys;
using SHZY.Business.Interfaces;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using SHZY.BaseData.Entitys;
using Org.BouncyCastle.Crypto;

namespace SHZY.Business;

/// <summary>
/// 业务实现：工单信息.
/// </summary>
[ApiDescriptionSettings(Tag = "Business", Name = "Workorder", Order = 200)]
[Route("api/Business/[controller]")]
public class QmsBusiWorkorderService : IQmsBusiWorkorderService, IDynamicApiController, ITransient
{
    /// <summary>
    /// 服务基础仓储.
    /// </summary>
    private readonly ISqlSugarRepository<QmsBusiWorkorderEntity> _repository;

    /// <summary>
    /// 多租户事务.
    /// </summary>
    private readonly ITenant _db;

    /// <summary>
    /// 用户管理.
    /// </summary>
    private readonly IUserManager _userManager;

    /// <summary>
    /// 初始化一个<see cref="QmsBusiWorkorderService"/>类型的新实例.
    /// </summary>
    public QmsBusiWorkorderService(
        ISqlSugarRepository<QmsBusiWorkorderEntity> qmsBusiWorkorderRepository,
        ISqlSugarClient context,
        IUserManager userManager)
    {
        _repository = qmsBusiWorkorderRepository;
        _db = context.AsTenant();
        _userManager = userManager;
    }

    /// <summary>
    /// 获取工单信息.
    /// </summary>
    /// <param name="id">主键值.</param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public async Task<dynamic> GetInfo(string id)
    {
        var output = await _repository.Context.Queryable<QmsBusiWorkorderEntity, QmsBaseMaterialEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.MaterialId == b.Id))
            .Where(a => a.Id == id)
            .Select((a,b)=> new QmsBusiWorkorderInfoOutput
            {
                id = a.Id,
                code = a.Code,
                type = a.Type,
                materialId = a.MaterialId,
                materialCode = b.Code,
                materialDes = b.Name,
                qty = a.Qty,
                unit = a.Unit,
                planStartTime = a.PlanStartTime,
                planEndTime = a.PlanEndTime,
                actualStartTime = a.ActualStartTime,
                actualEndTime = a.ActualEndTime,
                status = a.Status,
                remark = a.Remark,
            })
            .FirstAsync();

        var qmsBusiWorkorderdetailList = await _repository.Context.Queryable<QmsBusiWorkorderdetailEntity, QmsBaseMaterialEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.MaterialId == b.Id))
            .Where(a => a.WorkOrderId == output.id)
            .Select((a, b) => new QmsBusiWorkorderdetailInfoOutput
            {
                id = a.Id,
                materialId = a.MaterialId,
                materialCode = b.Code,
                materialDes = b.Name,
                qty = a.Qty,
            })
            .ToListAsync();
        output.qmsBusiWorkorderdetailList = qmsBusiWorkorderdetailList;

        return output;
    }

    /// <summary>
    /// 获取工单信息列表.
    /// </summary>
    /// <param name="input">请求参数.</param>
    /// <returns></returns>
    [HttpGet("")]
    public async Task<dynamic> GetList([FromQuery] QmsBusiWorkorderListQueryInput input)
    {
        var queryable = _repository.Context.Queryable<QmsBusiWorkorderEntity, QmsBaseMaterialEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.MaterialId == b.Id))
            .WhereIF(!string.IsNullOrEmpty(input.code), a => a.Code.Contains(input.code))
            .WhereIF(!string.IsNullOrEmpty(input.type), a => a.Type.Equals(input.type))
            .WhereIF(input.status != null, a => a.Status.Equals(input.status))
            .WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.Code.Contains(input.keyword) || a.Type.Contains(input.keyword))
             .Where(a => a.DeleteMark == null)
            .OrderByIF(string.IsNullOrEmpty(input.sidx), a => a.CreatorTime, OrderByType.Desc);
        if (!string.IsNullOrEmpty(input.sidx))
        {
            queryable.OrderBy(input.sidx + " " + input.sort);
        }
        var data = await queryable.Select((a, b) => new QmsBusiWorkorderListOutput
        {
            id = a.Id,
            code = a.Code,
            type = a.Type,
            materialId = SqlFunc.MergeString(b.Name, " " + b.Code),
            qty = a.Qty,
            unit = a.Unit,
            planStartTime = a.PlanStartTime,
            planEndTime = a.PlanEndTime,
            actualStartTime = a.ActualStartTime,
            actualEndTime = a.ActualEndTime,
            status = a.Status,
            remark = a.Remark,
        }).ToPagedListAsync(input.currentPage, input.pageSize);
        return PageResult<QmsBusiWorkorderListOutput>.SqlSugarPageResult(data);
    }

    /// <summary>
    /// 新建工单信息.
    /// </summary>
    /// <param name="input">参数.</param>
    /// <returns></returns>
    [HttpPost("")]
    public async Task Create([FromBody] QmsBusiWorkorderCrInput input)
    {
        var entity = input.Adapt<QmsBusiWorkorderEntity>();
        if (await _repository.Context.Queryable<QmsBusiWorkorderEntity>().Where(x => x.Code == entity.Code && x.DeleteMark == null).CountAsync() > 0)
        {
            throw Oops.Oh("工单号重复，请确认是否已经添加该工单");
        }

        try
        {
            // 开启事务
            _db.BeginTran();

            var isOk = await _repository.Context.Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
            if (!(isOk > 0)) throw Oops.Oh(ErrorCode.COM1000);

            var qmsBusiWorkorderdetailEntityList = input.qmsBusiWorkorderdetailList.Adapt<List<QmsBusiWorkorderdetailEntity>>();
            if(qmsBusiWorkorderdetailEntityList != null && qmsBusiWorkorderdetailEntityList.Count > 0)
            {
                foreach (var item in qmsBusiWorkorderdetailEntityList)
                {
                    item.WorkOrderId = entity.Id;
                }

                var isOk1 = await _repository.Context.Insertable(qmsBusiWorkorderdetailEntityList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
                if (!(isOk1 > 0)) throw Oops.Oh(ErrorCode.COM1000);
            }

            // 关闭事务
            _db.CommitTran();
        }
        catch (Exception)
        {
            // 回滚事务
            _db.RollbackTran();

            throw Oops.Oh(ErrorCode.COM1000);
        }
    }

    /// <summary>
    /// 获取工单信息无分页列表.
    /// </summary>
    /// <param name="input">请求参数.</param>
    /// <returns></returns>
    private async Task<dynamic> GetNoPagingList([FromQuery] QmsBusiWorkorderListQueryInput input)
    {
        var queryable = _repository.Context.Queryable<QmsBusiWorkorderEntity, QmsBaseMaterialEntity>((a, b) => new JoinQueryInfos(JoinType.Left, a.MaterialId == b.Id))
            .WhereIF(!string.IsNullOrEmpty(input.code), a => a.Code.Contains(input.code))
            .WhereIF(!string.IsNullOrEmpty(input.type), a => a.Type.Equals(input.type))
            .WhereIF(input.status != null, a => a.Status.Equals(input.status))
            .WhereIF(!string.IsNullOrEmpty(input.keyword), a => a.Code.Contains(input.keyword) || a.Type.Contains(input.keyword))
             .Where(a => a.DeleteMark == null)
            .OrderByIF(string.IsNullOrEmpty(input.sidx), a => a.CreatorTime, OrderByType.Desc);
        if (!string.IsNullOrEmpty(input.sidx))
        {
            queryable.OrderBy(input.sidx + " " + input.sort);
        }
        var data = await queryable.Select((a, b) => new QmsBusiWorkorderListOutput
        {
            id = a.Id,
            code = a.Code,
            type = a.Type,
            materialId = SqlFunc.MergeString(b.Name, " " + b.Code),
            qty = a.Qty,
            unit = a.Unit,
            planStartTime = a.PlanStartTime,
            planEndTime = a.PlanEndTime,
            actualStartTime = a.ActualStartTime,
            actualEndTime = a.ActualEndTime,
            status = a.Status,
            remark = a.Remark,
        }).ToListAsync();
        return data;
    }

    /// <summary>
    /// 导出工单信息.
    /// </summary>
    /// <param name="input">请求参数.</param>
    /// <returns></returns>
    [HttpGet("Actions/Export")]
    public async Task<dynamic> Export([FromQuery] QmsBusiWorkorderListQueryInput input)
    {
        var exportData = new List<QmsBusiWorkorderListOutput>();
        if (input.dataType == 0)
            exportData = Clay.Object(await GetList(input)).Solidify<PageResult<QmsBusiWorkorderListOutput>>().list;
        else
            exportData = await GetNoPagingList(input);
        List<ParamsModel> paramList = "[{\"value\":\"工单号\",\"field\":\"code\"},{\"value\":\"工单类型\",\"field\":\"type\"},{\"value\":\"物料ID\",\"field\":\"materialId\"},{\"value\":\"数量\",\"field\":\"qty\"},{\"value\":\"单位\",\"field\":\"unit\"},{\"value\":\"计划开始时间\",\"field\":\"planStartTime\"},{\"value\":\"计划完成时间\",\"field\":\"planEndTime\"},{\"value\":\"实际开始时间\",\"field\":\"actualStartTime\"},{\"value\":\"实际完成时间\",\"field\":\"actualEndTime\"},{\"value\":\"状态\",\"field\":\"status\"},{\"value\":\"备注\",\"field\":\"remark\"},]".ToList<ParamsModel>();
        ExcelConfig excelconfig = new ExcelConfig();
        excelconfig.FileName = "工单信息.xls";
        excelconfig.HeadFont = "微软雅黑";
        excelconfig.HeadPoint = 10;
        excelconfig.IsAllSizeColumn = true;
        excelconfig.ColumnModel = new List<ExcelColumnModel>();
        foreach (var item in input.selectKey.Split(',').ToList())
        {
            var isExist = paramList.Find(p => p.field == item);
            if (isExist != null)
                excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = isExist.field, ExcelColumn = isExist.value });
        }

        var addPath = FileVariable.TemporaryFilePath + excelconfig.FileName;
        ExcelExportHelper<QmsBusiWorkorderListOutput>.Export(exportData, excelconfig, addPath);
        var fileName = _userManager.UserId + "|" + addPath + "|xls";
        return new
        {
            name = excelconfig.FileName,
            url = "/api/File/Download?encryption=" + DESCEncryption.Encrypt(fileName, "SHZY")
        };
    }

    /// <summary>
    /// 批量删除工单信息.
    /// </summary>
    /// <param name="ids">主键数组.</param>
    /// <returns></returns>
    [HttpPost("batchRemove")]
    public async Task BatchRemove([FromBody] List<string> ids)
    {
        var entitys = await _repository.Context.Queryable<QmsBusiWorkorderEntity>().In(it => it.Id, ids).ToListAsync();
        if (entitys.Count > 0)
        {
            try
            {
                // 开启事务
                _db.BeginTran();

                // 批量删除工单信息
                var isOk = await _repository.Context.Updateable<QmsBusiWorkorderEntity>().SetColumns(it => new QmsBusiWorkorderEntity()
                {
                    DeleteTime = DateTime.Now,
                    DeleteMark = 1,
                    DeleteUserId = _userManager.UserId
                }).Where(it => ids.Contains(it.Id)).ExecuteCommandHasChangeAsync();

                // 清空工单明细信息表数据
                var isOk1 = await _repository.Context.Updateable<QmsBusiWorkorderdetailEntity>().SetColumns(it => new QmsBusiWorkorderdetailEntity()
                {
                    DeleteTime = DateTime.Now,
                    DeleteMark = 1,
                    DeleteUserId = _userManager.UserId
                }).Where(it => ids.Contains(it.WorkOrderId)).ExecuteCommandHasChangeAsync();

                // 关闭事务
                _db.CommitTran();
            }
            catch (Exception)
            {
                // 回滚事务
                _db.RollbackTran();
                throw Oops.Oh(ErrorCode.COM1002);
            }
        }
    }

    /// <summary>
    /// 更新工单信息.
    /// </summary>
    /// <param name="id">主键值.</param>
    /// <param name="input">参数.</param>
    /// <returns></returns>
    [HttpPut("{id}")]
    public async Task Update(string id, [FromBody] QmsBusiWorkorderUpInput input)
    {
        var entity = input.Adapt<QmsBusiWorkorderEntity>();
        if (await _repository.Context.Queryable<QmsBusiWorkorderEntity>().Where(x => x.Code == entity.Code&& x.Id!= entity.Id && x.DeleteMark == null).CountAsync() > 0)
        {
            throw Oops.Oh("工单号重复，请确认是否已经添加该工单");
        }

        try
        {
            // 开启事务
            _db.BeginTran();
            var isOk = await _repository.Context.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync();
            if (!isOk)
                throw Oops.Oh(ErrorCode.COM1001);

            // 清空工单明细信息原有数据
            await _repository.Context.Deleteable<QmsBusiWorkorderdetailEntity>().Where(it => it.WorkOrderId == entity.Id).ExecuteCommandAsync();

            // 新增工单明细信息新数据
            var qmsBusiWorkorderdetailEntityList = input.qmsBusiWorkorderdetailList.Adapt<List<QmsBusiWorkorderdetailEntity>>();
            if(qmsBusiWorkorderdetailEntityList != null && qmsBusiWorkorderdetailEntityList.Count > 0)
            {
                foreach (var item in qmsBusiWorkorderdetailEntityList)
                {
                    item.WorkOrderId = entity.Id;
                }

                var isOk1 = await _repository.Context.Insertable(qmsBusiWorkorderdetailEntityList).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync();
                if (!(isOk1 > 0)) throw Oops.Oh(ErrorCode.COM1001+"(明细)");
            }

            // 关闭事务
            _db.CommitTran();
        }
        catch (Exception)
        {
            // 回滚事务
            _db.RollbackTran();
            throw Oops.Oh(ErrorCode.COM1001);
        }
    }

    /// <summary>
    /// 删除工单信息.
    /// </summary>
    /// <returns></returns>
    [HttpDelete("{id}")]
    public async Task Delete(string id)
    {
        if(!await _repository.Context.Queryable<QmsBusiWorkorderEntity>().AnyAsync(it => it.Id == id))
        {
            throw Oops.Oh(ErrorCode.COM1005);
        }

        try
        {
            // 开启事务
            _db.BeginTran();

            // 批量删除工单信息
            var isOk = await _repository.Context.Updateable<QmsBusiWorkorderEntity>().SetColumns(it => new QmsBusiWorkorderEntity()
            {
                DeleteTime = DateTime.Now,
                DeleteMark = 1,
                DeleteUserId = _userManager.UserId
            }).Where(it => it.Id == id).ExecuteCommandHasChangeAsync();

            // 清空工单明细信息表数据
            var isOk1 = await _repository.Context.Updateable<QmsBusiWorkorderdetailEntity>().SetColumns(it => new QmsBusiWorkorderdetailEntity()
            {
                DeleteTime = DateTime.Now,
                DeleteMark = 1,
                DeleteUserId = _userManager.UserId
            }).Where(it => it.WorkOrderId == id).ExecuteCommandHasChangeAsync();

            // 关闭事务
            _db.CommitTran();
        }
        catch (Exception)
        {
            // 回滚事务
            _db.RollbackTran();

            throw Oops.Oh(ErrorCode.COM1002);
        }
    }

    /// <summary>
    /// 工单完工.
    /// </summary>
    /// <param name="input">参数.</param>
    /// <returns></returns>
    [HttpPost("Finish/{id}")]
    public async Task Finish(string id)
    {
        if (await _repository.Context.Queryable<QmsBusiWorkreportEntity>().Where(x => x.WorkOrderId == id && x.DeleteMark == null).CountAsync() == 0)
        {
            throw Oops.Oh("该工单还未报工，请先填写报工信息");
        }

        // 查询实际开始时间
        var entity1 = await _repository.Context.Queryable<QmsBusiWorkreportEntity>().Where(x => x.WorkOrderId == id && x.DeleteMark == null).OrderBy(x => x.ActualStartTime).FirstAsync();

        // 查询实际结束时间
        var entity2 = await _repository.Context.Queryable<QmsBusiWorkreportEntity>().Where(x => x.WorkOrderId == id && x.DeleteMark == null).OrderBy(x => x.ActualEndTime, OrderByType.Desc).FirstAsync();

        // 更新完工状态
        var isOk1 = await _repository.Context.Updateable<QmsBusiWorkorderEntity>().SetColumns(it => new QmsBusiWorkorderEntity()
        {
            ActualStartTime = entity1.ActualStartTime,
            ActualEndTime = entity2.ActualEndTime,
            Status = 2,
            LastModifyTime = DateTime.Now,
            LastModifyUserId = _userManager.UserId
        }).Where(x => x.Id == id).ExecuteCommandHasChangeAsync();
        if (!isOk1)
            throw Oops.Oh(ErrorCode.COM1001);

    }

}